//
//  YXTaskListViewController.m
//  MockProject
//
//  Created by FanYu on 8/20/16.
//  Copyright © 2016 niuzhaowang. All rights reserved.
//

#import "YXTaskListViewController.h"
#import "YXTaskListTableViewCell.h"
#import "YXDownloadManagerViewController.h"
#import "YXTaskManager.h"
#import "YXDownloaderManager.h"
#import "Config.h"
#import "YXUserDefault.h"
#import "Reachability.h"


@interface YXTaskListViewController () <UITableViewDelegate, UITableViewDataSource, YXTaskListTableViewCellDelegate>

@property (nonatomic, strong) UITableView *taskListTableView;
@property (nonatomic, strong) NSMutableArray *taskDataArray;
@property (nonatomic, strong) UILabel *hitLabel;
@property (nonatomic, strong) NSMutableDictionary *taskDownloadingDictionary;

@property (nonatomic) Reachability *hostReachability;
@property (nonatomic) Reachability *internetReachability;

@end

@implementation YXTaskListViewController

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"任务列表";

    [self setupUI];

    [self registerNotification];
    
    [self reachability];
    
    [self loadTaskData];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    [self refreshPage];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    [self.taskListTableView reloadData];
}


#pragma mark - Setup UI
- (void)setupUI {
    
    // table view
    self.taskListTableView = [[UITableView alloc] initWithFrame:self.view.frame];
    self.taskListTableView.backgroundColor = [UIColor whiteColor];
    self.taskListTableView.delegate = self;
    self.taskListTableView.dataSource = self;
    self.taskListTableView.rowHeight = 80;
    self.taskListTableView.allowsSelection = NO;
    self.taskListTableView.tableFooterView = [[UIView alloc] init];
    self.taskListTableView.separatorColor = [UIColor colorWithHexString:@"e0dcd9"];
    self.taskListTableView.backgroundColor = [UIColor colorWithHexString:@"f5f5f5"];
    [self.taskListTableView registerNib:[UINib nibWithNibName:@"YXTaskListTableViewCell" bundle:nil] forCellReuseIdentifier:@"YXTaskListCell"];
    [self.view addSubview:self.taskListTableView];
    
    // right navi button
    UIButton* barButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [barButton setImage:[UIImage imageNamed:@"下载管理icon正常态"] forState:UIControlStateNormal];
    [barButton setImage:[UIImage imageNamed:@"下载管理icon点击态"] forState:UIControlStateHighlighted];
    [barButton setTitle:@"下载管理" forState:UIControlStateNormal];
    [barButton setTitleColor:[UIColor colorWithHexString:@"bf390c"] forState:UIControlStateHighlighted];
    [barButton sizeToFit];
    [barButton.titleLabel setFont:[UIFont systemFontOfSize:12]];
    barButton.layer.borderWidth = 1;
    barButton.layer.borderColor = [UIColor whiteColor].CGColor;
    // iPhone4
    if ([SDVersion deviceSize] == Screen3Dot5inch) {
        barButton.layer.cornerRadius = 10;
        barButton.bounds = CGRectMake(0, 0, 80, 22);
    } else {
        barButton.layer.cornerRadius = 13 * kScaleFactor;
        barButton.bounds = CGRectMake(0, 0, 90 * kScaleFactor, 27 * kScaleFactor);
    }

    [barButton addTarget:self action:@selector(barButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [barButton addTarget:self action:@selector(barButtonTouchDown:) forControlEvents:UIControlEventTouchDown];
    
    UIBarButtonItem* customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:barButton];
    self.navigationItem.rightBarButtonItem = customBarButtonItem;
}

- (void)loadTaskData {
    self.taskDataArray = [YXTaskManager getTasksByTitleAscendingWithStatus:YXTaskStatusNA].mutableCopy;
}


#pragma mark - Notification 
- (void)registerNotification {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskStatusChangedNotification:) name:YXTaskStatusChangedNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appLifeCycleChangedNotification:) name:YXAppLifeCycleChangedNotification object:nil];
}


#pragma mark - Reachability
- (void)reachability {
    //开启网络状况的监听
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
    
    // 开始监听，会启动一个run loop
    self.hostReachability = [Reachability reachabilityWithHostName:@"www.baidu.com"];
    [self.hostReachability startNotifier];
}


#pragma mark - Actions
- (void)appLifeCycleChangedNotification:(NSNotification *)notification {
    if ([notification.object isEqualToString:@"DidEnterBackground"]) {
        [self pauseDueToReachabilityChanged];
    } else if ([notification.object isEqualToString:@"DidBecomeActive"]) {
        [self resumeDueToReachabilityChanged];
    } else if ([notification.object isEqualToString:@"WillTerminate"]) {
        [self pauseDueToReachabilityChanged];
    }
}

- (void)reachabilityChanged:(NSNotification *)notification {
    Reachability* curReach = [notification object];
    NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
    NetworkStatus status = [curReach currentReachabilityStatus];
    
    [YXUserDefault setReachability:status];
  
    // 没有网络
    if(status == NotReachable) {
        [self showAlert:@"当前没有网络哦～" message:nil];
        [self pauseDueToReachabilityChanged];
    }
    // 通过Wi-Fi下载
    else if (status == ReachableViaWiFi) {
        [self showAlert:@"已连接到WiFi网络" message:nil];
        [self resumeDueToReachabilityChanged];
    }
    // 通过手机流量下载
    else if (status == ReachableViaWWAN && ![YXUserDefault onlyDownloadOnWiFi]) {
        [self showAlert:@"已连接到手机网络" message:nil];
        [self resumeDueToReachabilityChanged];
    }
    // 手机流量 无法下载
    else if (status == ReachableViaWWAN && [YXUserDefault onlyDownloadOnWiFi]) {
        [self showAlert:@"当前使用的是手机流量，下载暂停" message:nil];
        [self pauseDueToReachabilityChanged];
    }
}

- (void)taskStatusChangedNotification:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];
    NSString *uid = [userInfo valueForKey:@"uid"];
    NSString *status = [userInfo valueForKey:@"status"];
    NSInteger maxConcurrencyNum = [YXUserDefault maxSimultaneouslyNumber].integerValue;

    // handle waiting to downloading
    if ([status isEqualToString:@"WaitingToDownloading"]) {
        if (self.taskDownloadingDictionary.count < maxConcurrencyNum) {
            if ([self.taskDownloadingDictionary objectForKey:uid] == nil) {
                [self reDownloadFailedTaskWithUID:uid];
            }
            [self.delegate changeTaskStatusToDownloadingWithUID:uid];
        }
    }
    // handle failed to downloading change
    else if ([status isEqualToString:@"Redownload"]) {
        [self handleFailedToDownloadingWithUID:uid maxConcurrency:maxConcurrencyNum];
    }
    // handle start all 
    else if ([status isEqualToString:@"StartAll"]) {
        [self handleStarAllTask];
    }
    // hanle pause all
    else if ([status isEqualToString:@"PauseAll"]) {
        [self.taskDownloadingDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [obj suspend];
        }];
    }
    // singel pause or resume 
    else {
        [self handleSinglePauseOrResumeWithStatus:status uid:uid];
    }
}

- (void)barButtonTapped:(UIButton *)sender {
    sender.layer.borderColor = [UIColor whiteColor].CGColor;
    
    YXDownloadManagerViewController *managerVC = [[YXDownloadManagerViewController alloc] init];
    managerVC.taskVC = self;
    
    [self.navigationController pushViewController:managerVC animated:YES];
}

- (void)barButtonTouchDown:(UIButton *)sender {
    sender.layer.borderColor = [UIColor colorWithHexString:@"bf390c"].CGColor;
}


#pragma mark - Helper
- (NSIndexPath *)getCellIndexPathWithSender:(UIButton *)sender {
    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.taskListTableView];
    NSIndexPath *indexPath = [self.taskListTableView indexPathForRowAtPoint:buttonPosition];
    return indexPath;
}

- (void)isShowHitLabel:(BOOL)isShow {
    if (isShow) {
        self.hitLabel.text = @"任务为空~";
        self.hitLabel.textColor = [UIColor blackColor];
        self.hitLabel.hidden = NO;
        [self.view addSubview:self.hitLabel];
        
        [self.hitLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self.view);
        }];
        
    } else {
        self.hitLabel.hidden = YES;
        [self.hitLabel removeFromSuperview];
    }
}

- (void)refreshPage {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self loadTaskData];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.taskListTableView reloadData];
        });
    });
}

- (void)saveFilePath:(id)filePath uid:(NSString *)uid {
    NSString *path = [[filePath absoluteString] substringFromIndex:7];
    [YXTaskManager updateTaskFilePath:path withUID:uid];
}

- (void)handleDownloadFinished:(NSString *)uid {
    [self.taskDownloadingDictionary removeObjectForKey:uid];
    [YXUserDefault setCurrentDownloadingNumber:self.taskDownloadingDictionary.count];
    
    NSArray *waitingTasks = [YXTaskManager getTasksWithStatus:YXTaskStatusWaiting byTimeline:NO];
    if (waitingTasks.count > 0) {
        DownloadTask *task = waitingTasks[0];
        
        [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:task.uid.integerValue];
        if ([self.taskDownloadingDictionary objectForKey:task.uid] == nil) {
            [self reDownloadFailedTaskWithUID:task.uid];
        }
        [self.delegate changeTaskStatusToDownloadingWithUID:task.uid];
    }
    
    // 要在这里更新状态，否则不进入下一个页面时，下一个页面收不到通知，在下一个页面更新状态没有效果
    [YXTaskManager updateTaskStatus:YXTaskStatusDownloaded withUID:uid.integerValue];
    [YXTaskManager updateTaskProgressPercent:0.0 withUID:uid];

    [self.delegate downloadFinishedForTaskUID:uid];
}

- (void)handleDownloadFailed:(NSString *)uid {
    [self.taskDownloadingDictionary removeObjectForKey:uid];
    [YXTaskManager updateTaskStatus:YXTaskStatusFailed withUID:uid.integerValue];
    [self.delegate downloadFailedForTaskUID:uid];
    [YXUserDefault setCurrentDownloadingNumber:self.taskDownloadingDictionary.count];
}

- (void)handleStarAllTask {
    // 开始已添加到下载队列中的任务
    [self.taskDownloadingDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        [obj resume];
        NSString *uid = [NSString stringWithFormat:@"%@", key];
        [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:uid.integerValue];
        [self.delegate changeTaskStatusToDownloadingWithUID:uid];
    }];
    // 如果未达Max，则将等待的任务添加到下载队列
    NSArray *allPauseTasks = [YXTaskManager getTasksWithStatus:YXTaskStatusPause byTimeline:NO];
    if (allPauseTasks.count > 0) {
        for (int i = (int)self.taskDownloadingDictionary.count; i < [YXUserDefault maxSimultaneouslyNumber].intValue; i ++) {
            if ((i - (int)self.taskDownloadingDictionary.count) < allPauseTasks.count) {
                DownloadTask *task = allPauseTasks[i - (int)self.taskDownloadingDictionary.count];
                [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:task.uid.integerValue];
                if ([self.taskDownloadingDictionary objectForKey:task.uid] == nil) {
                    [self reDownloadFailedTaskWithUID:task.uid];
                }
                [self.delegate changeTaskStatusToDownloadingWithUID:task.uid];
            }
        }
    }
    // 将暂停的任务设置为等待
    NSArray *allProcessingTasks = [YXTaskManager getTasksWithStatus:YXTaskStatusPause byTimeline:NO];
    for (DownloadTask *task in allProcessingTasks) {
        [YXTaskManager updateTaskStatus:YXTaskStatusWaiting withUID:task.uid.integerValue];
        [self.delegate changeTaskStatusToWaitingWithUID:task.uid];
    }
}

- (void)handleSinglePauseOrResumeWithStatus:(NSString *)status uid:(NSString *)uid {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.taskDownloadingDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            if ([key isEqualToString:uid]) {
                if ([status isEqualToString:@"Pause"]) {
                    [obj suspend];
                } else if ([status isEqualToString:@"Downloading"]){
                    [obj resume];
                }
            }
        }];
    });
}

- (void)handleFailedToDownloadingWithUID:(NSString *)uid maxConcurrency:(NSInteger)maxConcurrencyNum {
    if (self.taskDownloadingDictionary.count < maxConcurrencyNum) {
        [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:uid.integerValue];
        if ([self.taskDownloadingDictionary objectForKey:uid] == nil) {
            [self reDownloadFailedTaskWithUID:uid];
        }
        [self.delegate changeTaskStatusToDownloadingWithUID:uid];
    } else {
        [YXTaskManager updateTaskStatus:YXTaskStatusWaiting withUID:uid.integerValue];
        [self.delegate changeTaskStatusToWaitingWithUID:uid];
    }
}

- (void)reDownloadFailedTaskWithUID:(NSString *)uid {
    NSURLSessionDownloadTask *task = [YXDownloaderManager downloadTaskWithUID:uid.integerValue updateProgress:^(NSProgress *progress) {
        [self.delegate updateProgress:progress withTaskUID:uid];

    } updateSpeed:^(id speed) {
        [self.delegate updateSpeed:speed withTaskUID:uid];
        
    } downloadFinished:^(id done) {
        [self handleDownloadFinished:uid];
    } failure:^(NSError * error) {
        if (error != nil) {
            [self handleDownloadFailed:uid];
        }
    } filePath:^(id filePath) {
        [self saveFilePath:filePath uid:uid];
    }];
    
    [self.taskDownloadingDictionary setObject:task forKey:uid];
    [YXUserDefault setCurrentDownloadingNumber:self.taskDownloadingDictionary.count];
}

- (void)addTaskToDownloading:(UIButton *)sender {
    NSString *taskUID = [NSString stringWithFormat:@"%ld", sender.tag];
    // update tableview
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:sender.tag];
        [self loadTaskData];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.taskListTableView deleteRowsAtIndexPaths:@[[self getCellIndexPathWithSender:sender]] withRowAnimation:(UITableViewRowAnimationAutomatic)];
        });
    });
    
    // start a download
    NSURLSessionDownloadTask *task = [YXDownloaderManager downloadTaskWithUID:sender.tag updateProgress:^(NSProgress *progress) {
        [self.delegate updateProgress:progress withTaskUID:taskUID];
        
    } updateSpeed:^(id speed) {
        [self.delegate updateSpeed:speed withTaskUID:taskUID];
        
    } downloadFinished:^(id done) {
        [self handleDownloadFinished:taskUID];
        
    } failure:^(NSError * error) {
        if (error != nil) {
            [self handleDownloadFailed:taskUID];
        }
        
    } filePath:^(id filePath) {
        [self saveFilePath:filePath uid:taskUID];
    }];
    
    // save it to datebase
    [self.taskDownloadingDictionary setObject:task forKey:taskUID];
    [YXUserDefault setCurrentDownloadingNumber:self.taskDownloadingDictionary.count];
}

- (void)addTaskToWaiting:(UIButton *)sender {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [YXTaskManager updateTaskStatus:YXTaskStatusWaiting withUID:sender.tag];
        [self loadTaskData];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.taskListTableView deleteRowsAtIndexPaths:@[[self getCellIndexPathWithSender:sender]] withRowAnimation:(UITableViewRowAnimationAutomatic)];
        });
    });
}

- (void)resumeDueToReachabilityChanged {
    if (self.taskDownloadingDictionary.count != 0) {
        // resume all in downloading queue
        [self.taskDownloadingDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [obj resume];
            NSString *uid = [NSString stringWithFormat:@"%@", key];
            [YXTaskManager updateTaskStatus:YXTaskStatusDownloading withUID:uid.integerValue];
        
            [self.delegate changeTaskStatusToDownloadingWithUID:uid];
        }];
    
        // set reset tasks as waiting
        NSArray *inProcessTasks= [YXTaskManager getTasksForInProcessWithoutDownloading:NO];
        for (DownloadTask *task in inProcessTasks) {
            [YXTaskManager updateTaskStatus:YXTaskStatusWaiting withUID:task.uid.integerValue];
            [self.delegate changeTaskStatusToWaitingWithUID:task.uid];
        }
    }
}

- (void)pauseDueToReachabilityChanged {
    if (self.taskDownloadingDictionary.count != 0) {
        [self.taskDownloadingDictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [obj suspend];
        }];
    
        NSArray *inProcessTasks = [YXTaskManager getTasksForInProcess:NO];
        for (DownloadTask *task in inProcessTasks) {
            [YXTaskManager updateTaskStatus:YXTaskStatusPause withUID:task.uid.integerValue];
        };
    
        [self.delegate reachabilityChangedWithStatus:@"PauseAll"];
    }
}


#pragma mark - Alert
- (void)showAlert:(NSString *)title message:(NSString *)msg {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
    [self.navigationController presentViewController:alertController animated:YES completion:^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [alertController dismissViewControllerAnimated:YES completion:nil];
            [alertController removeFromParentViewController];
        });
    }];
}


#pragma mark - YXTaskListTableViewCellDelegate
- (void)downloadButtonTapped:(UIButton *)sender {
    NSInteger maxConcurrencyNum = [YXUserDefault maxSimultaneouslyNumber].integerValue;
    // no network
    if ([YXUserDefault reachability] == NotReachable) {
        [self showAlert:@"无法下载任务哦" message:@""];
    } else {
        // add to downloading
        if (self.taskDownloadingDictionary.count < maxConcurrencyNum) {
            [self addTaskToDownloading:sender];
        }
        // set task as waiting
        else {
            [self addTaskToWaiting:sender];
        }
    }
}


#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    [self isShowHitLabel:self.taskDataArray.count ==0 ? YES : NO];
    
    return self.taskDataArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    YXTaskListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YXTaskListCell" forIndexPath:indexPath];
    
    cell.taskModel = [YXTaskModel configTaskWithTitle:@"" size:@"" time:@"" downloadStatus:YXTaskStatusNA];
    cell.delegate = self;
    
    return cell;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    YXTaskListTableViewCell *taskCell = (YXTaskListTableViewCell *)cell;
    taskCell.taskModel = self.taskDataArray[indexPath.row];
}


#pragma mark - Lazy
- (NSMutableArray *)taskDataArray {
    if (!_taskDataArray) {
        _taskDataArray = [[NSMutableArray alloc] init];
    }
    return _taskDataArray;
}
- (NSMutableDictionary *)taskDownloadingDictionary {
    if (!_taskDownloadingDictionary) {
        _taskDownloadingDictionary = [[NSMutableDictionary alloc] init];
    }
    return _taskDownloadingDictionary;
}
- (UILabel *)hitLabel {
    if (!_hitLabel) {
        _hitLabel = [[UILabel alloc] init];
    }
    return _hitLabel;
}


@end
